#ifndef Define_LcClassifierRank
#define Define_LcClassifierRank


#include <cstdio>
#include <cstdlib>
#include <iostream>

#include <cstring>
#include <opencv2/opencv.hpp>
#include <opencv2/flann/config.h>

#include <opencv2/legacy/legacy.hpp>		// EM
#include <opencv2/contrib/contrib.hpp>		// colormap
#include <opencv2/nonfree/nonfree.hpp>		// SIFT

#include <algorithm>
#include "Classifier.h"
#include "VideoRead.h"
#include "FeatureComputer.h"

class LcGlobalExtractor
{
public:
	int dim;
	virtual void work(Mat & frm, Mat & desc){;}
};


#ifndef Define_LcColorSpaceType
#define Define_LcColorSpaceType

enum ColorSpaceType{
	LC_RGB,LC_LAB,LC_HSV
};
#endif



class ClassifierRank //this calss may do too many things
{
public:

	int veb;
	ClassifierRank();

	void setReader( LcVideoReadExt * n_reader );
	void setExtractor( LcFeatureExtractor * n_extractor );
	//this is for local feature extractor
	void setGlobalExtractor( LcGlobalExtractor * n_global_extractor);
	void setFeatureCode( const char * n_code_string );
	void setClassifier( LcClassifier * n_classifier);

	void trainPreFrame();
	void crossFrameTest();
	
	void Laplacian();
	virtual void cluster();

	//following public variables will be using in 
	vector<int> cluster_lab;
	int cluster_n;
	Mat retrival_feature;
	LcGlobalExtractor * global_extractor;
	vector< LcVideoReadVec* > cluster_readers;

	void extractGlobalFeature( Mat & global_desc );


	void getClassifierAffine(Mat & D);
	void getGlobalFeatAffine(Mat & D);

	float classifier_affine_weight;
	

	Mat getLaplacian( Mat & D);

	
	LcVideoReadExt * my_reader;
	LcFeatureExtractor * my_extractor;
	LcClassifier * my_classifier;
	const char * feature_code_string;

	Mat getNormLaplacian( Mat & D );

	static void EMcluster( Mat & specturm, std::vector<int> & lb,int cluster_n);

};

class Kmeans : public ClassifierRank
{
public:
	void cluster();

};

//==============================================



class LcHistogram : public LcGlobalExtractor
{
public:
	LcHistogram();
	int n1,n2,n3;
	ColorSpaceType color_type;
	void set(	ColorSpaceType n_color_type,
				int n_n1,
				int n_n2,
				int n_n3);

	void work(Mat & src, Mat & hist);

};

class LcGlobalHoG : public LcGlobalExtractor
{
public:
	LcGlobalHoG();
	int nwin_x;
	int nwin_y;
	int B; //set here the number of histogram bins

	void set(	int n_nwin_x,
				int n_nwin_y,
				int n_B);
				
	void work( Mat & src, Mat & hist);

};

class LcSpatialHoG : public LcGlobalExtractor
{
public:
	LcSpatialHoG();

	LcSpatialHoG(int n_spatial_code){ set(3,3,9,n_spatial_code);}

	int spatial_code;
	int nwin_x;
	int nwin_y;
	int B; //set here the number of histogram bins

	void set(	int n_nwin_x,
				int n_nwin_y,
				int n_B,
				int n_spatial_code);

	vector< Vec4f > win;

	void work(Mat & src, Mat & hist);

private:

	LcGlobalHoG my_hog;
};



class LcTopBottomHistogram : public LcGlobalExtractor
{
public:
	LcTopBottomHistogram();
	int n1,n2,n3;
	ColorSpaceType color_type;
	void set(	ColorSpaceType n_color_type,
				int n_n1,
				int n_n2,
				int n_n3);

	void work(Mat & src, Mat & hist);

private:

	LcHistogram my_histogram;
};

class LcGlobalCombiner : public LcGlobalExtractor
{
public:
	LcGlobalCombiner();

	LcGlobalCombiner( vector<int> & cite_codes);

	void set( vector<int> & cite_codes);

	void work( Mat & src, Mat & hist );

private:

	vector< LcGlobalExtractor * > my_computers;
};

class LcSpatialHistogram : public LcGlobalExtractor
{
public:
	LcSpatialHistogram();

	LcSpatialHistogram( int n_spatial_code )
	{ set( LC_HSV , 4,4,4, n_spatial_code ); }

	int spatial_code;
	int n1,n2,n3;
	ColorSpaceType color_type;

	vector< Vec4f > win;

	void set(	ColorSpaceType n_color_type,
				int n_n1,
				int n_n2,
				int n_n3,
				int n_spatial_code);

	void work(Mat & src, Mat & hist);

private:

	LcHistogram my_histogram;
};

#endif